package com.mlk.core.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Maps;
import com.mlk.core.config.DictConfig;
import com.mlk.core.exception.ParamException;
import com.mlk.rbac.dto.SysDictDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数据字典工具类
 * 帮助在业务系统使用数据字典的功能
 * 使用redis从缓存之中获取数据
 *
 * @author xulu
 */
@Component
@Slf4j
public class DictUtils {

    private static RedisTemplate<String, String> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 通过字典的类型获取到指定的字典项的列表内容
     *
     * @param dictType
     * @return
     */
    public static final List<SysDictDTO> getDictByTpye(String dictType) {
        String data = redisTemplate.opsForValue().get(DictConfig.DICT_PREFIX + dictType);
        return JSONUtils.jSONstringToObj(data, new TypeReference<List<SysDictDTO>>() {
        });
    }

    /**
     * 刷新对应的字典缓存
     *
     * @param items
     */
    public static final void refreshCache(List<SysDictDTO> items) {
        // 数据的组装
        Map<String, List<SysDictDTO>> dictMaps = items.stream().collect(Collectors.groupingBy(SysDictDTO::getTypeDesc));
        if (dictMaps.size() > 0) {
            Set<Map.Entry<String, List<SysDictDTO>>> entries = dictMaps.entrySet();

            for (Map.Entry<String, List<SysDictDTO>> entity : entries) {
                log.debug("redis save value , dict type_desc is {}", entity.getKey());
                redisTemplate.opsForValue().set(DictConfig.DICT_PREFIX + entity.getKey(), JSONUtils.toJSONString(entity.getValue()));
            }
            //end
        }
    }

    /**
     * 字典数据的适配对象
     * 将一个字典组转换成类似Map的形式,方便业务组件的使用
     */
    public static class DictAdapter{

        private DictAdapter() {
        }

        private Map<String,String> map = Maps.newHashMap();

        /**
         * 传入指定的字典组标识符,获取对应的适配对象
         * @param dictType
         * @return
         */
        public static DictAdapter adapt(String dictType){
           return  adapt(getDictByTpye(dictType));
        }

        /**
         * 将一个字典组转换成为适配对象
         *
         * @param items
         * @return
         */
        public static DictAdapter adapt(List<SysDictDTO> items) {
            if (CollectionUtils.isEmpty(items)) {
                return new DictAdapter();
            }

            if (items.stream().map(e -> e.getTypeDesc()).distinct().count() > 1) {
                throw new ParamException("item 不是同一个字典组的内容");
            }

            DictAdapter adapter = new DictAdapter();

            items.forEach(e -> {
                adapter.map.put(e.getDictKey(), e.getDictValue());
            });

            return adapter;
        }

        /**
         * 从适配器之中获取值
         * @param key
         * @return
         */
        public String get(String key){
            return this.map.get(key);
        }

        /**
         * 从适配器之中获取int值
         * @param key
         * @return
         */
        public Integer getIntValue(String key){
            return Integer.parseInt(this.get(key));
        }

        /**
         * 从适配之中获取boolean值
         * @param key
         * @return
         */
        public Boolean getBooleanValue(String key){
            return Boolean.parseBoolean(this.get(key));
        }

        /**
         * 从适配之中获取long值
         * @param key
         * @return
         */
        public  Long getLongValue(String key){
            return Long.parseLong(this.get(key));
        }

    }
}
